package com.xz.xzutils.module.xzmybatislogplus.listener;

import com.intellij.DynamicBundle;
import com.intellij.execution.ExecutionListener;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.execution.ui.RunnerLayoutUi;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.ui.content.Content;
import com.xz.xzutils.components.console.SqlConsole;
import com.xz.xzutils.components.console.SqlConsoleCreator;
import com.xz.xzutils.icons.MyIcons;
import com.xz.xzutils.module.xzmybatislogplus.socket.SqlReceiver;
import com.xz.xzutils.module.xzmybatislogplus.dto.SocketPort;
import com.xz.xzutils.utils.MyBatisDetector;
import lombok.Data;
import org.jetbrains.annotations.NotNull;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import javax.swing.*;

/**
 * <p>
 * RUN/DEBUG 模式启动监听器
 * 可以在程序启动用时做一些操作
 * </p>
 *
 * @author DONG.WANG17@HAND-CHINA.COM
 * @since 2025-01-14 14:34
 */
public class MyExecutionListener implements ExecutionListener {
    private final DynamicBundle messageBundle = new DynamicBundle(MyExecutionListener.class, "messages.MybatisLogPlus");
    private static final Logger LOGGER = Logger.getInstance(MyExecutionListener.class);
    private static final Map<Integer, String> runningServices = new ConcurrentHashMap<>();
    private SqlConsole sqlConsole;

    @Override
    public void processStarted(@NotNull String executorId, @NotNull ExecutionEnvironment env, @NotNull ProcessHandler handler) {
        // 判断项目是否使用 mybatis
        if (!MyBatisDetector.isMyBatisUsed(env.getProject())) {
            // System.out.println("processStarted 项目未使用 mybatis");
            return;
        }
        // 监听 RUN/DEBUG 模式启动
        if ("Run".equals(executorId) || "Debug".equals(executorId)) {
            RunContentDescriptor descriptor = env.getContentToReuse();
            if (null == descriptor) {
                return;
            }
            // 初始化 sql 查看面板
            initSqlConsole(env.getProject(), descriptor);
            if (null == this.sqlConsole) return;

            // 获取端口 JvmArgsExtension 设置的
            Integer port = env.getProject().getUserData(SocketPort.SOCKET_PORT);
            if (null == port) return;

            SqlReceiver sqlReceiver = new SqlReceiver(port, this.sqlConsole, env.getProject());
            sqlReceiver.start();
        }
    }

    @Override
    public void processTerminated(@NotNull String executorId, @NotNull ExecutionEnvironment env, @NotNull ProcessHandler handler, int exitCode) {
        Integer port = env.getProject().getUserData(SocketPort.SOCKET_PORT);
        // SQL 解析器关闭，端口:{0},程序退出代码:{1}
        this.sqlConsole.logInfo(messageBundle.getMessage("xzmybatislogplus.sql.parser.shutdown", port, exitCode));
        ExecutionListener.super.processTerminated(executorId, env, handler, exitCode);
    }


    // 模块

    private void initSqlConsole(@NotNull Project project, @NotNull RunContentDescriptor descriptor) {
        if (null != descriptor.getRunnerLayoutUi()) {
            this.sqlConsole = SqlConsoleCreator.createSqlConsole(project);
            JComponent consolePanel = sqlConsole.getComponent();

            // 在运行窗口中添加自定义的 sql 查看面板
            //RunnerLayoutUi runnerLayoutUi = descriptor.getRunnerLayoutUi();
            //Content content = runnerLayoutUi.createContent("Sql From Mybatis", consolePanel, "Sql From Mybatis", MyIcons.PLUGIN_ICONS, consolePanel);
            //content.setCloseable(false);
            //runnerLayoutUi.addContent(content);

            RunnerLayoutUi runnerLayoutUi = descriptor.getRunnerLayoutUi();
            final Content sqlFromMybatis = runnerLayoutUi.getContentManager().getFactory().createContent(consolePanel, "SQL日志", false);
            sqlFromMybatis.setCloseable(false);
            sqlFromMybatis.setIcon(MyIcons.PLUGIN_ICONS);
            runnerLayoutUi.getContentManager().addContent(sqlFromMybatis);
        }
    }

    private ProcessInfo getProcessInfo(@NotNull ExecutionEnvironment env, @NotNull ProcessHandler handler) {
        // 安全获取配置（添加空检查）
        RunConfiguration config = Optional.ofNullable(env.getRunnerAndConfigurationSettings())
                .map(RunnerAndConfigurationSettings::getConfiguration)
                .orElse(null);
        String serviceId = config != null ? config.getName() : "unknown_config";

        // 安全获取模块名
        Module module = ModuleUtil.findModuleForFile(Objects.requireNonNull(env.getProject().getProjectFile()), env.getProject());
        String moduleName = module != null ? module.getName() : "unknown_module";

        // 获取 PID
        int pid = -1;
        try {
            // 反射获取 Process
            Method getProcessMethod = handler.getClass().getMethod("getProcess");
            Process process = (Process) getProcessMethod.invoke(handler);
            pid = (int) process.pid();
        } catch (Exception e) {
            LOGGER.error("获取进程ID失败", e);
        }
        ProcessInfo processInfo = new ProcessInfo();
        processInfo.setPid(pid);
        processInfo.setModuleName(moduleName);
        processInfo.setProjectName(env.getProject().getName());
        processInfo.setServiceId(serviceId);
        processInfo.setProjectPath(env.getProject().getBasePath());
        return processInfo;
    }

    @Data
    private static class ProcessInfo {
        private int pid;
        private String serviceId;
        private String moduleName;
        private String projectName;
        private String projectPath;
    }
}
